#include "cfgparser.h"
#include "agentsocket.h"
#include <fstream>
#include <sstream>

CfgParser::CfgParser(bool isServer)
: m_isServer(isServer)
, m_admins(0)
, m_agent_ips(0)
, m_agent_hosts(0)
, m_fsThreshold(0)
, m_laThreshold(0)
, m_freeMemThreshold(0)
, m_servicePath("")
{
    //server's regexp
    m_commentMatcher.assign("^#[[:print:]]*");
    m_spaceMatcher.assign("^[[:space:]]+[[:print:]]*");
    m_agentsMatcher.assign("^\\[agents\\]\\ *");
    m_admMatcher.assign("^\\[administrators\\]\\ *");
    m_botMatcher.assign("^\\[bot\\]\\ *");
    m_ipMatcher.assign("[[:digit:]]{1,3}.[[:digit:]]{1,3}.[[:digit:]]{1,3}.[[:digit:]]{1,3}");
    m_jidMatcher.assign("[[:alnum:]\\.]{1,255}@[[:alnum:]\\.]{1,255}[[:alpha:]]{2,4}");
    //agent's regexp
    m_servicesMatcher.assign("^\\[services\\]\\ *");
    m_alertsMatcher.assign("^\\[alerts\\]\\ *");
    m_fsThresholdMatcher.assign("^\\[fs_threshold\\]\\ *");
    m_laThresholdMatcher.assign("^\\[la_threshold\\]\\ *");
    m_memThresholdMatcher.assign("^\\[mem_threshold\\]\\ *");
    m_pathMatcher.assign("^\\[service_path\\]\\ *");

    m_admins = new list<string>;
    m_agent_ips = new vector<string>;
    m_agent_hosts = new vector<string>;
    m_alerts = new list<string>;
    m_services = new map<string, bool>;
    if (m_isServer)
        openServerConfig();
    openAgentConfig();
    if (!this->isConfigValid())
        exit(0);
}

CfgParser::~CfgParser()
{
    delete m_agent_ips;
    delete m_agent_hosts;
    delete m_admins;
    delete m_alerts;
    delete m_services;
}

void CfgParser::openServerConfig()
{
    const char * filename = "/usr/local/etc/jbmon/server.conf";
    string line, type;
    ifstream in(filename);
    if (in.is_open())
    {
        while (!in.eof())
        {
            getline(in, line);
            if (!boost::regex_match(line, m_commentMatcher) && !boost::regex_match(line, m_spaceMatcher) && !line.empty())
            {
                if (boost::regex_match(line, m_agentsMatcher))
                {
                    type = "agent";
                    continue;
                }
                else if (boost::regex_match(line, m_admMatcher))
                {
                    type = "adm";
                    continue;
                }
                else if (boost::regex_match(line, m_botMatcher))
                {
                    type = "bot";
                    continue;
                }
                if (type == "agent")
                {
                    int pos = line.find(":");
                    if (pos != std::string::npos)
                    {
                        string ip = line.substr(pos + 1, line.length() - pos - 1);
                        if (boost::regex_match(ip, m_ipMatcher))
                        {
                            m_agent_hosts->push_back(line.substr(0, pos));
                            m_agent_ips->push_back(ip);
                        }
                    }
                }
                else if (type == "adm" && boost::regex_match(line, m_jidMatcher))
                    m_admins->push_back(line);

                else if (type == "bot")
                {
                    int pos = line.find(":");
                    if (pos == std::string::npos && boost::regex_match(line, m_ipMatcher))
                        m_botIp = line;
                    else
                    {
                        string jid = line.substr(0, pos);
                        if (boost::regex_match(jid, m_jidMatcher))
                            m_botJid = jid;
                        m_botPswd = line.substr(pos + 1, line.length() - pos - 1);
                    }
                }
            }
        }

        in.close();
    }

}

//this function return 1 if config is valid and 0 if config is invalid

bool CfgParser::isConfigValid()
{
    if (m_isServer)
    {
        if (m_admins->empty())
        {
            std::cout << "config error: administrators section" << std::endl;
            return 0;
        }
        if (m_agent_hosts->empty() || m_agent_ips->empty())
        {
            std::cout << "config error: agents section" << std::endl;
            return 0;
        }
        if (m_botIp.empty() || m_botJid.empty() || m_botPswd.empty())
        {
            std::cout << "config error: bot section" << std::endl;
            return 0;
        }
    }
    else
    {
        if (m_services->empty())
        {
            std::cout << "config error: services section" << std::endl;
            return 0;
        }
        if (m_alerts->empty())
        {
            std::cout << "config error: alerts section" << std::endl;
            return 0;
        }
        if (m_fsThreshold <= 0)
        {
            std::cout << "config error: fs_threshold section" << std::endl;
            return 0;
        }
        if (m_laThreshold <= 0)
        {
            std::cout << "config error: la_threshold section" << std::endl;
            return 0;
        }
        if (m_freeMemThreshold <= 0)
        {
            std::cout << "config error: mem_threshold section" << std::endl;
            return 0;
        }
        if (m_servicePath.empty())
        {
            std::cout << "config error: services_path section" << std::endl;
            return 0;
        }
    }
    return 1;
}

void CfgParser::openAgentConfig()
{
    const char * filename = "/usr/local/etc/jbmon/agent.conf";
    string line;
    uint type;
    ifstream in(filename);
    if (in.is_open())
    {
        while (!in.eof())
        {
            getline(in, line);
       
            if (!boost::regex_match(line, m_commentMatcher) && !boost::regex_match(line, m_spaceMatcher) && !line.empty())
            {
                if (boost::regex_match(line, m_servicesMatcher))
                {
                    type = 0x1;
                    continue;
                }
                else if (boost::regex_match(line, m_alertsMatcher))
                {
                    type = 0x11;
                    continue;
                }
                else if (boost::regex_match(line, m_fsThresholdMatcher))
                {
                    type = 0x10;
                    continue;
                }
                else if (boost::regex_match(line, m_laThresholdMatcher))
                {
                    type = 0x111;
                    continue;
                }
                else if (boost::regex_match(line, m_pathMatcher))
                {
                    type = 0x101;
                    continue;
                }
                else if (boost::regex_match(line, m_memThresholdMatcher))
                {
                    type = 0x1111;
                    continue;
                }
                if (type == 0x1)
                    m_services->insert(std::make_pair(line, 1));

                else if (type == 0x11)
                    m_alerts->push_back(line);
                else if (type == 0x10)
                    m_fsThreshold = atoi(line.c_str());
                else if (type == 0x111)
                    m_laThreshold = atof(line.c_str());
                else if (type == 0x101)
                    m_servicePath = line;
                else if (type == 0x1111)
                    m_freeMemThreshold = atoi(line.c_str());



            }
        }
        in.close();
    }

}
